// ==============================================================================================
// ╦  ┬┌─┐┌─┐┌┐┌┌─┐┌─┐    Yaksha Programming Language
// ║  ││  ├┤ │││└─┐├┤     is Licensed with GPLv3 + extra terms. Please see below.
// ╩═╝┴└─┘└─┘┘└┘└─┘└─┘
// Note: libs - MIT license, runtime/3rd - various
// ==============================================================================================
// GPLv3:
//
// Yaksha - Programming Language.
// Copyright (C) 2020 - 2024 Bhathiya Perera
//
// This program is free software: you can redistribute it and/or modify it under the terms
// of the GNU General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program.
// If not, see https://www.gnu.org/licenses/.
//
// ==============================================================================================
// Additional Terms:
//
// Please note that any commercial use of the programming language's compiler source code
// (everything except compiler/runtime, compiler/libs and compiler/3rd) require a written agreement
// with author of the language (Bhathiya Perera).
//
// If you are using it for an open source project, please give credits.
// Your own project must use GPLv3 license with these additional terms.
//
// You may use programs written in Yaksha/YakshaLisp for any legal purpose
// (commercial, open-source, closed-source, etc) as long as it agrees
// to the licenses of linked runtime libraries (see compiler/runtime/README.md).
//
// ==============================================================================================
// entry_struct_func_compiler.h
#ifndef ENTRY_STRUCT_COMPILER_H
#define ENTRY_STRUCT_COMPILER_H
#include "datatype_compiler.h"
#include "utilities/ykdt_pool.h"
#include <unordered_map>
namespace yaksha {
  struct entry_data {
    ykdatatype *key_dt_;
    ykdatatype *val_dt_;
    unsigned int incremented_id_;
  };
  struct func_data {
    [[maybe_unused]] ykdatatype *input_type_;
    [[maybe_unused]] ykdatatype *output_type_;
    [[maybe_unused]] unsigned int increment_id_;
  };
  struct tuple_data {
    [[maybe_unused]] ykdatatype *tuple_dt_;
    unsigned int incremented_id_;
  };
  struct entry_struct_func_compiler {
    explicit entry_struct_func_compiler(ykdt_pool *pool);
    std::string compile(ykdatatype *entry_dt, datatype_compiler *dtc);
    std::string compile_tuple(ykdatatype *tuple_dt, datatype_compiler *dtc);
    std::string compile_function_dt(ykdatatype *function_dt,
                                    datatype_compiler *dtc);
    std::string compile_binary_data(const std::string &data);
    std::string compile_fixed_array(ykdatatype *fixed_array_dt,
                                    datatype_compiler *dtc);
    void compile_forward_declarations(std::stringstream &target);
    void compile_structures(std::stringstream &target);
    void compile_function_defs(std::stringstream &target);
    void compile_binary_data_to(std::stringstream &target);
    void compiled_fixed_array_to(std::stringstream &target);
    bool has_structures();
    bool has_functions();
    bool has_bin_data();
    bool has_fixed_arrays();
    ~entry_struct_func_compiler();

private:
    std::string improve_name(const std::string &yaksha_datatype_string,
                             const std::string &numbered_name);
    std::unordered_map<std::string, std::string> name_improvements_;
    std::unordered_map<std::string, std::string> reverse_name_improvements_;
    // ------------------------------------------------
    ykdt_pool *pool_;
    std::stringstream forward_decls_;
    // Autogenerated structures
    unsigned int counter_;
    std::vector<entry_data> autogen_structs_list_;
    std::unordered_map<std::string, unsigned int> autogen_structs_;
    std::stringstream code_;
    // Autogenerated function typedefs
    unsigned int counter_functions_;
    std::vector<func_data> autogen_func_typedef_list_;
    std::unordered_map<std::string, unsigned int> autogen_func_typedefs_;
    std::stringstream code_fnc_;
    // Autogenerated Tuple structures
    unsigned int counter_tuples_;
    std::vector<tuple_data> autogen_tuple_list_;
    std::unordered_map<std::string, unsigned int> autogen_tuples_;
    std::stringstream code_tuples_;
    // Autogenerated Binary Data
    unsigned int counter_bin_data_;
    std::unordered_map<std::string, unsigned int> autogen_bin_data_;
    std::stringstream bin_data_;
    // Auto generated fixed array, typedefs
    unsigned int counter_fxa_;
    std::vector<tuple_data> autogen_fxa_list_;
    std::unordered_map<std::string, unsigned int> autogen_fxa_;
    std::stringstream code_fxa_;
  };
}// namespace yaksha
#endif
